using System;
using System.Reflection;

namespace Avanzis.QueryObjects
{
    public abstract class PersistentPropertyBase
    {
        protected PropertyInfo propertyInfo;
        protected ColumnPropertyAttribute columnPropertyAttribute;

        protected PersistentPropertyBase()
        {
        }

        protected PersistentPropertyBase(PropertyInfo propertyInfo, ColumnPropertyAttribute propertyAttribute)
        {
            this.propertyInfo = propertyInfo;
            this.columnPropertyAttribute = propertyAttribute;
        }

        public PropertyInfo PropertyInfo
        {
            get { return propertyInfo; }
        }

        public ColumnPropertyAttribute ColumnPropertyAttribute
        {
            get { return columnPropertyAttribute; }           
        } 

        public virtual object GetValue(object instance)
        {
            object propertyValue = this.PropertyInfo.GetValue(instance, null);

            if (this.ColumnPropertyAttribute.ColumnType != null)
            {
                string columnType = this.ColumnPropertyAttribute.ColumnType;
                if (columnType.IndexOf(".") < 0)                
                    columnType = "System." + columnType;                
                Type convertionType = Type.GetType(columnType);
                propertyValue = System.Convert.ChangeType(propertyValue, convertionType);                                             
            }           

            return propertyValue;
        }

        public void SetValue(object instance, object value)
        {
            try
            {
                object convertedValue;

                if (value == System.DBNull.Value)
                {
                    convertedValue = null;
                }
                else
                {
                    if (this.PropertyInfo.PropertyType.IsEnum)
                    {
                        if (value is String)
                        {
                            convertedValue = Enum.Parse(this.PropertyInfo.PropertyType, (String)value);
                        }
                        else
                        {
                            convertedValue = Enum.ToObject(this.PropertyInfo.PropertyType, value);
                        }
                    }
                    else
                    {
                        convertedValue = System.Convert.ChangeType(value, this.PropertyInfo.PropertyType);
                    }
                }
                this.PropertyInfo.SetValue(instance, convertedValue, null);
            }
            catch
            {
                throw;
            }
        }
    }
}
